package cn.jsu.oj.dispatchServer.satellite.util;

import java.io.*;

/**
 * byte工具
 *
 * @author shan
 * @date 2022/07/01
 */
public class ByteUtil {


    /**
     * obj转byte[]
     *
     * @param object 对象
     * @return {@link byte[] }
     */
    public static byte[] objToByteArray(Object object) {
        byte[] bytes = null;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(object);
            objectOutputStream.flush();
            bytes = byteArrayOutputStream.toByteArray();
            objectOutputStream.close();
            byteArrayOutputStream.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        return bytes;
    }

    /**
     * byte[]转obj
     *
     * @param bytes 字节
     * @return {@link Object }
     */
    public static Object byteArrayToObj(byte[] bytes) {
        Object object = null;
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            object = objectInputStream.readObject();
            objectInputStream.close();
            byteArrayInputStream.close();
        } catch (IOException | ClassNotFoundException exception) {
            exception.printStackTrace();
        }
        return object;
    }

    /**
     * 字节数组转 short，小端
     *
     * @param array 数组
     * @return short
     */
    public static short byteArrayToShortLittleEndian(byte[] array) {
        if (array.length > 2) {
            return 0;
        }
        short value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((array[i] & 0xff) << (i * 8));
        }
        return value;
    }

    /**
     * 字节数组转 short，大端
     *
     * @param array 数组
     * @return short
     */
    public static short byteArrayToShortBigEndian(byte[] array) {
        if (array.length > 2) {
            return 0;
        }
        short value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 int，小端
     *
     * @param array 数组
     * @return int
     */
    public static int byteArrayToIntLittleEndian(byte[] array) {
        if (array.length > 4) {
            return 0;
        }

        int value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((array[i] & 0xff) << (i * 8));
        }
        return value;
    }

    /**
     * 字节数组转 int，大端
     *
     * @param array 数组
     * @return int
     */
    public static int byteArrayToIntBigEndian(byte[] array) {
        if (array.length > 4) {
            return 0;
        }
        int value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 float，小端
     *
     * @param array 数组
     * @return float
     */
    public static float byteArrayToFloatLittleEndian(byte[] array) {
        if (array.length != 4) {
            return 0;
        }
        return Float.intBitsToFloat(byteArrayToIntLittleEndian(array));
    }

    /**
     * 字节数组转 float，大端
     *
     * @param array 数组
     * @return float
     */
    public static float byteArrayToFloatBigEndian(byte[] array) {
        if (array.length > 4) {
            return 0;
        }
        return Float.intBitsToFloat(byteArrayToIntBigEndian(array));
    }

    /**
     * 字节数组转 long，小端
     *
     * @param array 数组
     * @return long
     */
    public static long byteArrayToLongLittleEndian(byte[] array) {
        if (array.length != 8) {
            return 0;
        }
        long value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((long) (array[i] & 0xff) << (i * 8));
        }
        return value;
    }

    /**
     * 字节数组转 long，大端
     *
     * @param array 数组
     * @return long
     */
    public static long byteArrayToLongBigEndian(byte[] array) {
        if (array.length != 8) {
            return 0;
        }
        long value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((long) (array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 double，小端
     *
     * @param array 数组
     * @return double
     */
    public static double byteArrayToDoubleLittleEndian(byte[] array) {
        if (array.length != 8) {
            return 0;
        }
        return Double.longBitsToDouble(byteArrayToLongLittleEndian(array));
    }

    /**
     * 字节数组转 double，大端
     *
     * @param array 数组
     * @return double
     */
    public static double byteArrayToDoubleBigEndian(byte[] array) {
        if (array.length != 8) {
            return 0;
        }
        return Double.longBitsToDouble(byteArrayToLongBigEndian(array));
    }

    /**
     * 字节数组转 HexString
     *
     * @param array 数组
     * @return {@link String }
     */
    public static String byteArrayToHexString(byte[] array) {
        StringBuilder builder = new StringBuilder();
        for (byte b : array) {
            String s = Integer.toHexString(b & 0xff);
            if (s.length() < 2) {
                builder.append("0");
            }
            builder.append(s);
        }

        return builder.toString().toUpperCase();
    }

    /**
     * short 转字节数组，小端
     *
     * @param s 年代
     * @return {@link byte[] }
     */
    public static byte[] shortToByteArrayLittleEndian(short s) {
        byte[] array = new byte[2];
        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * short 转字节数组，大端
     *
     * @param s 年代
     * @return {@link byte[] }
     */
    public static byte[] shortToByteArrayBigEndian(short s) {
        byte[] array = new byte[2];
        for (int i = 0; i < array.length; i++) {
            array[array.length - 1 - i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * int 转字节数组，小端
     *
     * @param s 年代
     * @return {@link byte[] }
     */
    public static byte[] intToByteArrayLittleEndian(int s) {
        byte[] array = new byte[4];
        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * int 转字节数组，大端
     *
     * @param s 年代
     * @return {@link byte[] }
     */
    public static byte[] intToByteArrayBigEndian(int s) {
        byte[] array = new byte[4];
        for (int i = 0; i < array.length; i++) {
            array[array.length - 1 - i] = (byte) (s >> (i * 8));
        }
        return array;
    }

    /**
     * float 转字节数组，小端
     *
     * @param f f
     * @return {@link byte[] }
     */
    public static byte[] floatToByteArrayLittleEndian(float f) {
        return intToByteArrayLittleEndian(Float.floatToIntBits(f));
    }

    /**
     * float 转字节数组，大端
     *
     * @param f f
     * @return {@link byte[] }
     */
    public static byte[] floatToByteArrayBigEndian(float f) {
        return intToByteArrayBigEndian(Float.floatToIntBits(f));
    }

    /**
     * long 转字节数组，小端
     *
     * @param l l
     * @return {@link byte[] }
     */
    public static byte[] longToByteArrayLittleEndian(long l) {
        byte[] array = new byte[8];
        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (l >> (i * 8));
        }
        return array;
    }

    /**
     * long 转字节数组，大端
     *
     * @param l l
     * @return {@link byte[] }
     */
    public static byte[] longToByteArrayBigEndian(long l) {
        byte[] array = new byte[8];
        for (int i = 0; i < array.length; i++) {
            array[array.length - 1 - i] = (byte) (l >> (i * 8));
        }
        return array;
    }

    /**
     * double 转字节数组，小端
     *
     * @param d d
     * @return {@link byte[] }
     */
    public static byte[] doubleToByteArrayLittleEndian(double d) {
        return longToByteArrayLittleEndian(Double.doubleToLongBits(d));
    }

    /**
     * double 转字节数组，大端
     *
     * @param d d
     * @return {@link byte[] }
     */
    public static byte[] doubleToByteArrayBigEndian(double d) {
        return longToByteArrayBigEndian(Double.doubleToLongBits(d));
    }

    /**
     * HexString 转字节数组
     *
     * @param hexString 十六进制字符串
     * @return {@link byte[] }
     */
    public static byte[] hexString2ByteArray(String hexString) {
        if (hexString.length() % 2 != 0) {
            return null;
        }
        byte[] array = new byte[hexString.length() / 2];
        int value = 0;
        for (int i = 0; i < hexString.length(); i++) {
            char s = hexString.charAt(i);
            if (i % 2 == 0) {
                value = Integer.parseInt(String.valueOf(s), 16) * 16;
            } else {
                value += Integer.parseInt(String.valueOf(s), 16);
                array[i / 2] = (byte) value;
                value = 0;
            }
        }
        return array;
    }
}
